/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once


#include "core/设备内存缓存.h"
#include "引擎枚举数据.h"
#include "引擎数据类型.h"

#include <array>


EngineAPI_EXPORT S_绘图框架* f_创建绘图框架(E_绘图API apiName);

EngineAPI_EXPORT void* f_draw_创建绘图设备(S_设备环境& dev);
EngineAPI_EXPORT void  f_draw_销毁绘图设备(void* 绘图设备);

Inline S_渲染环境* f_df_get绘图环境(S_设备环境& ctx) { return (S_渲染环境*)(ctx.m_绘图环境); }


E_绘图API	f_get后端框架名称();

EngineAPI_EXPORT void*		f_get设备();
EngineAPI_EXPORT void*		f_get命令列表();
EngineAPI_EXPORT void*		f_get环境();

void* f_df_getVK设备(S_设备环境& ctx);


S_板载缓存*	f_创建GUP常量缓存(E_板载缓存类型 type, uint64 size);



EngineAPI_EXPORT S_着色* f_create着色(S_设备环境& ctx, S_着色器创建配置 ini, S_结构对象** 布局 = nullptr, uint32 布局数量 = 0);
EngineAPI_EXPORT S_着色* f_create着色(S_设备环境& ctx, S_着色器管线创建参数 ini);
EngineAPI_EXPORT S_管线* f_create线管(S_设备环境& ctx, S_着色& shader, const S_线管创建参数& 线管参数, std::string name = "");
EngineAPI_EXPORT S_管线* f_df_创建计算线管(S_设备环境& ctx, S_着色& shader, std::string name="");


EngineAPI_EXPORT S_着色*		f_df_创建计算着色管线(S_设备环境& ctx, S_着色器管线创建参数 ini);
EngineAPI_EXPORT S_着色线管*	f_df_创建材质着色器(S_设备环境& ctx,
											S_材质管线* material, 
											const S_着色器创建配置& 图元配置, 
											S_线管创建参数& 线管参数, 
											S_结构对象** 布局 = nullptr,
											uint32 布局数量 = 0,
											E_管线槽 管线槽 = E_管线槽::e_颜色渲染);

//EngineAPI_EXPORT S_着色线管*	f_df_创建材质着色器(S_设备环境& ctx,
//										 S_材质管线* material, 
//										 const S_着色器创建配置& 图元配置, 
//										 S_线管创建参数& 线管参数,
//										 E_管线槽 管线槽 = E_管线槽::e_颜色渲染);


EngineAPI_EXPORT void	f_df_创建渲染着色管线(S_设备环境& ctx,
										S_材质管线* material, 
										const S_着色器管线创建参数& 图元配置, 
										const S_线管创建参数& 线管参数,
										uint32 管线槽);


void f_df_创建材质管线(S_设备环境& ctx,
					 S_材质管线* material, 
					 const S_着色器创建配置& 图元配置, 
					 S_线管创建参数& 线管参数, 
					 S_结构对象** 布局 = nullptr,
					 uint32 布局数量 = 0,
					 uint32 管线槽 = E_管线槽::e_颜色渲染);

void f_df_创建材质管线(S_设备环境& ctx,
				 S_材质管线* material, 
				 const S_着色器创建配置& 图元配置, 
				 S_线管创建参数& 线管参数,
				 uint32 管线槽 = E_管线槽::e_颜色渲染);


EngineAPI_EXPORT void f_df_销毁材质着色器(S_材质管线* material);

void f_df_构建着色器描述符集(S_着色线管* 材质管线, std::vector<C_DescriptorSet*>& ds);




t_着色参数设置 f_df_创建着色器参数布局(void* device, const std::vector<S_着色器创建参数>& m_参数布局, S_GPU参数槽* 分配槽);
C_DescriptorSetLayout* f_df_创建着色器参数布局(S_设备环境& ctx, const std::vector<S_着色器创建参数>& 参数布局);
void f_df_绑定参数布局(S_设备环境& ctx, S_结构对象* 参数布局);
void f_df_销毁绑定参数布局(S_设备环境& ctx, S_结构对象* 参数布局);

S_结构对象* f_df_createDescriptorSet(S_设备环境& ctx, C_DescriptorSetLayout& layout);
void		f_df_releaseDescriptorSet(S_设备环境& ctx, S_结构对象* layout);



EngineAPI_EXPORT S_管线*		f_df_create光追管线(S_设备环境& ctx, S_光追后端* 光追后端, const S_着色器创建配置& 线管参数);
EngineAPI_EXPORT S_光追后端*	f_df_create光追后端(S_设备环境& ctx, const S_着色器创建配置& 线管参数);
EngineAPI_EXPORT void        f_df_销毁光追后端(S_光追后端* 光追后端);
EngineAPI_EXPORT void		f_df_光追后端_重构着色器(S_光追后端* rt);
EngineAPI_EXPORT void		f_bd_安装光追材质着色器(S_光追后端* rt, int32 loc, std::string path, uint32 光追ID);
EngineAPI_EXPORT void		f_bd_删除光追材质着色器(S_光追后端* rt, int32 loc);
EngineAPI_EXPORT bool		f_bd_GLSLtoSPV(E_着色阶段 阶段, const std::string code, const std::string 保存路径);
EngineAPI_EXPORT void		f_df_构建顶层光追加速(S_渲染层& 渲染层, uint32 num, bool 更新 = false);


EngineAPI_EXPORT void	f_push板载缓存(S_着色* shader, void* data, uint64 bitSize);

EngineAPI_EXPORT S_结构指针	f_gpu_创建参数布局(S_板载缓存* 渲染参数, uint32 binding, uint32 阶段分布);


EngineAPI_EXPORT void f_df_allocGPU参数缓存槽(S_GPU参数槽* layout, uint16 num);
EngineAPI_EXPORT void f_df_freeGPU参数缓存槽(S_GPU参数槽* layout);


EngineAPI_EXPORT void	f_setGPU参数布局_2D绘制(S_着色* shader, S_2D绘制GPU全局参数& view);
EngineAPI_EXPORT void	f_setGPU参数布局(S_GPU计算* GPU, const S_GPU参数布局& GPU参数);
EngineAPI_EXPORT void	f_df_setGPU参数布局(S_结构指针 device, const S_GPU参数槽& GPU参数, bool 内存块 = true);
EngineAPI_EXPORT void	f_df_upGPU计算参数(S_GPU计算* device, const S_GPU参数槽& GPU参数);
EngineAPI_EXPORT void	f_df_upGPU参数(S_结构指针 device, S_结构指针 GPU参数设置, const S_GPU参数槽& GPU参数, bool 内存块 = true);
EngineAPI_EXPORT void	f_df_upGPU参数(S_结构指针 device, const S_GPU参数槽& GPU参数, bool 内存块 = true);



//void f_绑定Vertex(S_设备环境& ctx, S_板载缓存* bg);
//void f_绑定Index(S_设备环境& ctx, S_板载缓存* buf);


EngineAPI_EXPORT void f_Draw_序列(S_设备环境& ctx, S_着色线管* 着色线管, S_板载缓存* 顶点, S_渲染参数& 渲染参数);
EngineAPI_EXPORT void f_Draw_间接序列(S_设备环境& ctx, S_着色线管* 着色线管, S_板载缓存* 顶点, S_渲染参数& 渲染参数);
EngineAPI_EXPORT void f_Draw_索引三角形(S_设备环境& ctx, S_着色线管* 着色线管, S_板载缓存* vert, S_索引渲染参数& 索引渲染参数, S_渲染参数& 渲染参数);
EngineAPI_EXPORT void f_Draw2D_索引三角形(S_设备环境& ctx, S_着色线管* 着色线管, S_板载缓存* vert, S_索引渲染参数& 索引渲染参数, S_渲染参数& 渲染参数);




//void f_RayDraw_索引三角形(S_设备环境& ctx, S_材质* material, S_索引渲染参数& 索引渲染参数, S_渲染参数& 渲染参数);
//void f_Draw2D点(S_设备环境& ctx, std::vector<S_板载缓存*>& bg, S_渲染参数& 渲染参数, bool 是否填充);
//void f_Draw2D线(S_设备环境& ctx, std::vector<S_板载缓存*>& bg, S_渲染参数& 渲染参数, bool 是否闭合);
//void f_Draw2D多边形(S_设备环境& ctx, std::vector<S_板载缓存*>& bg, S_渲染参数& 渲染参数);
//S_渲染环境* f_创建渲染环境(S_设备环境& ctx, E_MS次数 采样);


EngineAPI_EXPORT S_帧缓存*	f_bd_创建帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理** colors, uint32 num, bool 多重采样 = true, bool 单一层 = false);
EngineAPI_EXPORT void		f_bd_构建帧多重采样缓存(S_设备环境& ctx, S_帧缓存* frame, const uvec2& faceSize, S_纹理** colors, uint32 num);
EngineAPI_EXPORT void		f_bd_构建帧缓存纹理(S_设备环境& ctx, S_帧缓存* frame, const uvec2& faceSize, S_纹理** colors, uint32 num);
EngineAPI_EXPORT void		f_bd_重置帧缓存大小(S_设备环境& ctx, S_帧缓存* frame, const uvec2& faceSize);

EngineAPI_EXPORT S_帧缓存*	f_fb_创建立方体帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理* color, S_纹理* depth);
EngineAPI_EXPORT void		f_fb_重置立方体帧缓存(S_帧缓存* fb, uvec2 faceSize);

EngineAPI_EXPORT S_帧缓存*	f_fb_创建阴影帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理* 深度纹理);
EngineAPI_EXPORT void		f_fb_重置阴影帧缓存(S_帧缓存* fb, uvec2 faceSize);

EngineAPI_EXPORT S_帧缓存*	f_fb_创建合成帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理* color, E_MS次数 采样次数);
EngineAPI_EXPORT void		f_fb_重置合成帧缓存(S_帧缓存* fb, uvec2 faceSize);

EngineAPI_EXPORT S_帧缓存*	f_fb_创建几何缓存帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理** color, S_纹理* depth, uint32 纹理数量);
EngineAPI_EXPORT void		f_fb_重置几何缓存帧缓存(S_帧缓存* fb, uvec2 faceSize);

S_帧缓存*	f_fb_创建UI渲染帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理* color[4]);
void		f_fb_重置UI渲染帧缓存(S_设备环境& ctx, S_帧缓存* frame, const uvec2& faceSize, S_纹理* color[2]);

S_帧缓存*	f_fb_创建3D场景帧缓存(S_设备环境& ctx, const uvec2& faceSize, S_纹理* color, S_纹理* depth);
void		f_fb_重置3D场景帧缓存(S_帧缓存* fb, const uvec2& faceSize, S_纹理* tex[]);


EngineAPI_EXPORT void		f_fb_销毁帧缓存(S_帧缓存* fb);



EngineAPI_EXPORT S_设备环境* f_df_创建渲染环境(S_设备环境& ctx, E_纹理格式 cf, E_纹理格式 df, E_MS次数 采样, uint16 线程数 = 1);
EngineAPI_EXPORT S_设备环境* f_创建计算环境(S_设备环境& ctx, uint16 线程数 = 1);

EngineAPI_EXPORT bool f_df_销毁渲染环境(S_设备环境& ctx);




EngineAPI_EXPORT S_子集绘图命令* f_bd_创建子集绘图命令(S_渲染环境* 绘图设备, uint32 线程数量);
EngineAPI_EXPORT void f_Draw_Begin(S_子集绘图命令* 绘图命令, uint8 id);
EngineAPI_EXPORT void f_Draw_end(S_子集绘图命令* 绘图命令, uint8 id);

EngineAPI_EXPORT void f_Draw_Begin_帧缓存(S_设备环境& ctx, S_帧缓存* frame, uint8 id, bool 阴影 = false);
EngineAPI_EXPORT void f_Draw_Begin_帧缓存(S_设备环境& ctx, S_帧缓存* frame, uint8 id, S_Rect2D rect);
EngineAPI_EXPORT void f_Draw_end_帧缓存(S_设备环境& ctx);

void f_df_BeginDraw(S_设备环境* 绘图配置, S_帧缓存* frame, uint8 id, uint32 清除数量);


//void f_Draw_Begin_帧缓存(S_设备环境* 绘图配置, S_帧缓存* frame, S_结构指针 命令缓存, uint8 id);
//void f_Draw_end_帧缓存(S_设备环境* 绘图配置, S_结构指针 命令缓存, S_结构指针 fenc = nullptr);



void f_Draw_Begin(S_结构指针 命令缓存, S_设备环境* 绘图配置, S_帧缓存* frame, uint8 id);
void f_Draw_end(S_结构指针 命令缓存, S_设备环境* 绘图配置);

void f_Draw_Begin(S_设备环境* ctx, uint8 id);
void f_Draw_end(S_设备环境* ctx);

void f_Draw_Begin(S_设备环境* ctx, S_结构指针 命令缓存, S_结构指针 fence);
void f_Draw_end(S_设备环境* ctx, S_结构指针 命令缓存, S_结构指针 fence, uint8 列队=0);


//void f_surface_构建底层加速结构(S_Mesh* mesh);
EngineAPI_EXPORT void f_Draw_构建底层加速结构(S_设备环境* 绘图配置, uint8 id);
EngineAPI_EXPORT void f_Draw_构建顶层加速结构(S_设备环境* 绘图配置, S_帧缓存* frame, uint8 id);



EngineAPI_EXPORT S_GPU计算* f_df_创建并行计算(S_设备环境& ctx, std::string path, const std::vector<S_着色器创建参数>& 参数配置, const std::vector<S_常量推送创建参数>& 常量 = {}, bool 自定义布局 = false);
EngineAPI_EXPORT void		f_df_销毁并行计算(S_GPU计算* in);

EngineAPI_EXPORT void f_GPU_run计算(S_GPU计算* gpu, uvec3 dim, void* 常量推送 = nullptr, uint32 size = 0, uint8 列队 = 0);
EngineAPI_EXPORT void f_df_run计算(S_GPU计算* gpu, uvec3 dim, S_GPU参数槽& 参数槽, void* 常量推送 = nullptr, uint8 列队 = 0);
EngineAPI_EXPORT void f_bd_GPU计算_图像合成(S_GPU计算* gpu, uvec3 dim, void* 常量推送 = nullptr, uint32 size = 0, uint8 列队 = 0);

EngineAPI_EXPORT bool	f_device_是否支持光追(const S_设备& dev);
EngineAPI_EXPORT bool	f_device_是否支持光追(const S_物理设备& dev);

EngineAPI_EXPORT S_设备 f_get最强计算性能设备(const std::vector<S_设备>& 设备);

EngineAPI_EXPORT uvec3 f_df_get全局最大线程(S_设备环境& ctx);
EngineAPI_EXPORT uvec3 f_df_get本地最大线程(S_设备环境& ctx);
EngineAPI_EXPORT uint32 f_def_get本地最大线程数量(S_设备环境& ctx);


EngineAPI_EXPORT S_GlobalParam f_df_全局GPU参数();
EngineAPI_EXPORT void	f_df_光追渲染(GLSL_RenderFrame& 帧渲染参数, S_光追后端* 光追后端);



void f_frameBuf_set采样(S_设备环境& ctx, S_帧缓存* 帧缓存, E_纹理格式 纹理格式);
void f_df_钳制视口大小(S_设备环境& ctx, ivec2& viewSize);
void f_df_钳制视口大小(S_设备环境& ctx, uvec2& viewSize);
void f_df_钳制纹理大小(S_设备环境& ctx, uvec2& viewSize);
void f_df_钳制纹理大小(S_设备环境& ctx, uvec3& viewSize);



void f_tex_拷贝纹理(S_设备环境& ctx, S_纹理* des, S_纹理* src, const std::vector<uvec2>& 区域);


void f_pipe_着色参数设置创建(S_设备环境& ctx);
void f_pipe_着色线管布局创建(S_设备环境& ctx);
void f_pipe_着色线管布局销毁(S_设备环境& ctx);

void f_pipe_销毁着色参数设置(S_设备环境& ctx);

/**************************************** 窗口绘制面 *****************************************/

void f_df_windowSurface(S_设备环境& ctx, S_WindowSurface* surface, ivec2 size);





Inline constexpr vec2 f_df_视口采样偏移(uint32 offset) {
	vec2 viewOffset[32] = {
		{0,0},
		{0,1},
		{1,0},
		{0,-1},
		{-1,0},
		{0.707107,	0.707107},
		{0.707107,	-0.707107},
		{-0.707107,	-0.707107},
		{-0.707107,	0.707107},

		{0,2},
		{1,1.7321},
		{1.7321,1},
		{2,0},
		{1.7321,-1},
		{1,-1.7321},
		{0,-2},
		{-1,-1.7321},
		{-1.7321,-1},
		{-2,0},
		{-1.7321,1},
		{-1,1.7321},
	};
	return viewOffset[offset];
}

Inline constexpr float32 f_df_视口采样权重(uint32 offset) {
	float32 viewSizeOffset[32] = {
		0,
		0.2,
		0.2,
		0.2,
		0.2,
		0.2,
		0.2,
		0.2,
		0.2,

		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
		0.35,
	};
	return viewSizeOffset[offset];
}





//废弃
EngineAPI_EXPORT void	f_df_setGPU参数槽(S_结构指针 device, S_结构指针 GPU参数设置, const S_GPU参数槽& GPU参数);


//void f_Draw_Begin(S_结构指针 命令缓存, S_设备环境* 绘图配置, S_帧缓存* frame, uint8 id);
//void f_Draw_end(S_结构指针 命令缓存, S_设备环境* 绘图配置);

//S_GPU计算* f_gpu_创建并行计算(S_设备环境& ctx, std::string& GLSL_code, const std::vector<S_着色器创建参数>& 参数配置, const std::vector<S_着色器常量推送创建参数>& 常量 = {});


